#ifndef ALGORITHM_GENETIC__
#define ALGORITHM_GENETIC__

#include <map>
#include <list>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iomanip>

#include "algorithm.h"
#include "area.h"
#include "options_genetic.h"

/** Trifazovy geneticky algoritmus. Pracuje s resenimi ve forme poradi vysilacu (permutace) pro
 * vstup do sekvencniho algoritmu.
 */
class GeneticAlgorithm: public Algorithm {
public:
	/** Defaultni konstruktor trifazoveho genetickeho algoritmu.
	 * \param o nastaveni trifazoveho genetickeho algoritmu
	 */
	GeneticAlgorithm(Options * o):options((GeneticOptions *)o), Algorithm(o) {};
	/** Konstruktor rovnou prirazujici i mapu se zadanim.
	 * \param a mapa zadani
	 * \param o nastaveni trifazoveho genetickeho algoritmu
	 */
	GeneticAlgorithm(Area * a, Options * o): Algorithm(o), options((GeneticOptions *)o) {
		area = a;
	}
	virtual bool Solve();
	/** Vypise do logu informace o nastaveni algoritmu.
	 */
	virtual void PrintInfo() {
		options->Log() << "Geneticky algoritmus skladajici se ze 3 casti: \r\n - regular interval assignment \r\n - greedy assignment \r\n - genetic algorithm assignment" << std::endl;
	}
	/** Vrati detail nastaveni algoritmu.
	 * \return popis nastaveni algoritmu
	 */
	std::string GetDetail() {
		return "genetic: " + options->GetTitle(false);
	}
	void PrintGeneration(int ** generation, int size);
private:
	void Regular();
	int * CreateOrderedList(bool * chosen, int & call_size);
	bool Greedy(bool * chosen);
	void Genetic(int * best_sequential);
	void Mutate(int * individual, int size);
	void CrossOver(int * p1, int * p2, int * positions, int * individual, int size);
	int ** Generate(int cnt);
	int AssignFrequencies(int * call_list, int size, bool break_on_fail = false);
	int REA(int * call_list, int size);
	int CountDegree();
	int * MixArray(int * a, int size);
	GeneticOptions * options; ///< nastaveni trifazoveho genetickeho algoritmu
};

#endif
